#include "tcpServer.hpp"
#include <memory>
using namespace std;
using namespace reactor;

#define USAGE(arg) std::cout << "\nUsage\n\t" << argv[0] << " port " << std::endl \
                             << endl;

enum
{
    OK = 0,
    DIV_ZERO,
    MOD_ZERO,
    OP_ERROR
};

// 网络计算器业务逻辑
void handlerEnter(const Request &req, Response &resp)
{
    int x = req.x;
    int y = req.y;
    char op = req.op;

    int exitcode = 0;
    int result = 0;

    switch (op)
    {
    case '+':
        result = x + y;
        break;
    case '-':
        result = x - y;
        break;
    case '*':
        result = x * y;
        break;
    case '/':
    {
        if (0 == y)
            exitcode = DIV_ZERO;
        else
        {
            result = x / y;
        }
    }
    break;
    case '%':
    {
        if (0 == y)
            exitcode = MOD_ZERO;
        else
        {
            result = x % y;
        }
    }
    break;
    default:
        exitcode = OP_ERROR;
        break;
    }

    resp.exitcode = exitcode;
    resp.result = result;
}

void calculate(Connection *con)
{

    std::string onePackage;
    while (recvPackage(con->_sock, con->_inbuffer, &onePackage))
    {
        string reqstr;
        // 1.去掉请求报头
        deLenth(onePackage, reqstr);
        Request req;
        // 2.对请求字符串反序列化
        req.deserialize(reqstr);
        Response resp;
        // 3.构建响应
        handlerEnter(req, resp);
        // 4.对响应序列化
        string respstr;
        resp.serialize(&respstr);
        // 5.构建响应报头,并添加到连接数据结构的发送缓冲区中
        string sendstr;
        enLenth(respstr, sendstr);

        con->_outbuffer += sendstr;
        std::cout << "--------result: " << sendstr << std::endl;
    }
    // 可以直接发送，因为我们设置的发送是非阻塞的，即使发送事件没就绪也不影响
    con->_sender(con);
    // 如果没有写完，将写事件推入epoll模型
    // if (!con->_outbuffer.empty())
    //     con->_tsvp->enableReadWrite(con, true, true);
    // else
    //     con->_tsvp->enableReadWrite(con, true, false);
        
}
int main(int argc, char *argv[])
{
    if (argc != 2)
    {
        USAGE(argv[0]);
        exit(USAGE_ERR);
    }
    uint16_t port = atoi(argv[1]);
    unique_ptr<TcpServer> psvr(new TcpServer(calculate, port));
    psvr->InitServer();
    psvr->depatch();
    return 0;
}
